﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace TTGame {
/// <summary>
/// 注意一点 这个字典扩展就是为了SFS到字典转换做的 理论上字典的value不应该出现null值 如果有那就是用错了
/// </summary>
public static class SFSDictExt {
    private static bool isStringAndEmpty(object val) {
        if(val is string && val.ToString().Trim().Length == 0) {
            return true;
        }
        return false;
    }


    private static readonly string IntFilter = "+-0123456789";
    private static readonly string FloatFilter = "+-0123456789.eE";
    private static string atoFilter(string input, string validChars) {
        int i;
        string result = "";
        int powerseriesIndex = -1;
        for(i = 0; i < input.Length; i++) {
            if(input[i] == ' ') {
                continue;
            }
            if(input[i] == '.') {
                result += ".";
                continue;
            }
            if(input[i] == 'e' || input[i] == 'E') {
                result += "|";
                powerseriesIndex = i;
                continue;
            }
            if(powerseriesIndex != -1 && i == powerseriesIndex + 1) {
                result += input[i];
                continue;
            }
            if(validChars.IndexOf(input[i]) >= 0) {
                result += input[i];
            } else break;
        }
        return result;
    }

    private static object atoi(object input) {
        if(!(input is string)) {
            return input;
        }
        var filterResult = atoFilter(input.ToString(), IntFilter);
        if(string.IsNullOrEmpty(filterResult))
            filterResult = "0";
        return filterResult;
    }

    private static object atof(object input) {
        if(!(input is string)) {
            return input;
        }
        var filterResult = atoFilter(input.ToString(), FloatFilter);
        if(string.IsNullOrEmpty(filterResult))
            filterResult = "0";
        string[] filters;
        if(filterResult.Contains("|")) {
            filters = filterResult.Split('|');
            if(filters.Length == 2) {
                float float1 = filters[0].floatValue();
                if(filters[1].StartsWith("+")) {
                    for(int i = 0; i < filters[1].TrimStart('+').intValue(); i++) {
                        float1 *= 10;
                    }
                } else if(filters[1].StartsWith("-")) {
                    for(int i = 0; i < filters[1].TrimStart('-').intValue(); i++) {
                        float1 /= 10;
                    }
                }
                filterResult = float1.stringValue();
            }
        }
        return filterResult;
    }

    public static KeyValuePair<TK, TV> Last<TK, TV>(this IDictionary<TK, TV> source) {
        if(source == null) {
            return default(KeyValuePair<TK, TV>);
        }
        var iter = source.GetEnumerator();
        KeyValuePair<TK, TV> result = default(KeyValuePair<TK, TV>);
        while(iter.MoveNext()) {
            result = iter.Current;
        }
        return result;
    }
    public static KeyValuePair<TK, TV> First<TK, TV>(this IDictionary<TK, TV> source) {
        if(source == null) {
            return default(KeyValuePair<TK, TV>);
        }
        var iter = source.GetEnumerator();
        while(iter.MoveNext()) {
            return iter.Current;
        }
        return default(KeyValuePair<TK, TV>);
    }

    public static int FindFirstNotOf(this string source, string chars) {
        if(source == null) return -1;
        if(chars == null) return -1;
        if(source.Length == 0) return -1;
        if(chars.Length == 0) return 0;

        for(int i = 0; i < source.Length; i++) {
            if(chars.IndexOf(source[i]) == -1) return i;
        }
        return -1;
    }

    public static int FindLastNotOf(this string source, string chars) {
        if(source == null) return -1;
        if(chars == null) return -1;
        if(source.Length == 0) return -1;
        if(chars.Length == 0) return source.Length - 1;

        for(int i = source.Length - 1; i >= 0; i--) {
            if(chars.IndexOf(source[i]) == -1) return i;
        }
        return -1;
    }

    public static void checkOrAdd(this IDictionary dict, object key, object value) {
        if(dict.Contains(key)) {
            dict[key] = value;
        } else {
            dict.Add(key, value);
        }
    }

    private static readonly string ERROR_LOG = "注意这里理论上不应该出现字典中value为null的情况！！！！";

    public static bool boolValue(this object obj) {
        if(obj == null) {
            return false;
        }
        if(obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return false;
        } else if(obj.stringValue() == "0" || obj.stringValue().ToLower() == "false") {
            return false;
        }
        return true;
    }
    public static string stringValue(this object obj) {
        return Convert.ToString(obj);
    }

    public static int intValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToInt32(atoi(obj));
    }
    public static long longValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToInt64(atoi(obj));
    }
    public static ulong ulongValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToUInt64(atoi(obj));
    }
    public static uint uintValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToUInt32(atoi(obj));
    }
    public static double doubleValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToDouble(atof(obj));
    }
    public static float floatValue(this object obj) {
        if(obj != null && obj is string && string.IsNullOrEmpty(obj.ToString())) {
            return 0;
        }
        return Convert.ToSingle(atof(obj));
    }

    public static Dictionary<string, object> dictValue2(this object obj) {
        if(obj == null) {
            return null;
        }
        if(!(obj is IDictionary)) {
            return null;
        }
        //if(obj is string && string.IsNullOrEmpty(obj.ToString())) {
        //    return null;
        //}
        return (Dictionary<string, object>)obj;
    }

    public static Dictionary<string, object> dictValue(this object obj) {
        if(obj == null) {
            return new Dictionary<string, object>();
        }
        if(!(obj is IDictionary)) {
            return new Dictionary<string, object>();
        }
        //if(obj is string && string.IsNullOrEmpty(obj.ToString())) {
        //    return new Dictionary<string, object>();
        //}
        return (Dictionary<string, object>)obj;
    }

    public static IList listValue(this object obj) {
        if(obj == null) {
            return null;
        }
        if(!(obj is IList)) {
            return null;
        }
        //if(obj is string && string.IsNullOrEmpty(obj.ToString())) {
        //    return null;
        //}
        return (IList)obj;
    }

    public static object objectForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
            }
            return result;
        }
        return null;
    }

    public static void setObject(this IDictionary<string, object> dict, object value, string key) {
        dict[key] = value;
    }

    public static bool objectForKey(this IDictionary<string, object> dict, string key, out object value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
            }
            value = result;
            return true;
        } else {
            value = null;
            return false;
        }
    }

    public static string valueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return "";
            }
            return Convert.ToString(result);
        } else {
            return "";
        }
    }

    public static bool valueForKey(this IDictionary<string, object> dict, string key, out string value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = "";
            } else {
                value = Convert.ToString(result);
            }
            return true;
        } else {
            value = "";
            return false;
        }
    }

    public static Dictionary<string, object> dictValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return null;
            }
            return (Dictionary<string, object>)(result);
        } else {
            return null;
        }
    }

    public static bool dictValueForKey(this IDictionary<string, object> dict, string key, out Dictionary<string, object> value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = null;
            } else {
                value = (Dictionary<string, object>)(result);
            }
            return true;
        } else {
            value = null;
            return false;
        }
    }

    public static bool boolValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            return result.boolValue();
        } else {
            return false;
        }
    }

    public static bool boolValueForKey(this IDictionary<string, object> dict, string key, out bool value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = false;
            } else if(isStringAndEmpty(result)) {
                value = false;
            } else {
                value = result.boolValue();
            }
            return true;
        } else {
            value = false;
            return false;
        }
    }

    public static int intValueForKey(this IDictionary<string, object> dict, string key, int defaultValue = 0) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return defaultValue;
            } else if(isStringAndEmpty(result)) {
                return defaultValue;
            } else if(result is IList || result is IDictionary) {
                return defaultValue;
            }
            return Convert.ToInt32(atoi(result));
        } else {
            return defaultValue;
        }
    }

    public static bool intValueForKey(this IDictionary<string, object> dict, string key, out int value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else if(result is IList || result is IDictionary) {
                value = 0;
            } else {
                value = Convert.ToInt32(atoi(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }

    public static long longValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return 0;
            } else if(isStringAndEmpty(result)) {
                return 0;
            }
            return Convert.ToInt64(atoi(result));
        } else {
            return 0;
        }
    }

    public static bool longValueForKey(this IDictionary<string, object> dict, string key, out long value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else {
                value = Convert.ToInt64(atoi(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }

    public static ulong ulongValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return 0;
            } else if(isStringAndEmpty(result)) {
                return 0;
            }
            return Convert.ToUInt64(atoi(result));
        } else {
            return 0;
        }
    }

    public static bool ulongValueForKey(this IDictionary<string, object> dict, string key, out ulong value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else {
                value = Convert.ToUInt64(atoi(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }

    public static uint uintValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return 0;
            } else if(isStringAndEmpty(result)) {
                return 0;
            }
            return Convert.ToUInt32(atoi(result));
        } else {
            return 0;
        }
    }

    public static bool uintValueForKey(this IDictionary<string, object> dict, string key, out uint value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else {
                value = Convert.ToUInt32(atoi(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }

    public static double doubleValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return 0;
            } else if(isStringAndEmpty(result)) {
                return 0;
            }
            return Convert.ToDouble(atof(result));
        } else {
            return 0;
        }
    }

    public static bool doubleValueForKey(this IDictionary<string, object> dict, string key, out double value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else {
                value = Convert.ToDouble(atof(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }

    public static float floatValueForKey(this IDictionary<string, object> dict, string key) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                return 0;
            } else if(isStringAndEmpty(result)) {
                return 0;
            }
            return Convert.ToSingle(atof(result));
        } else {
            return 0;
        }
    }

    public static bool floatValueForKey(this IDictionary<string, object> dict, string key, out float value) {
        object result;
        if(dict.TryGetValue(key, out result)) {
            if(result == null) {
                UnityEngine.Debug.LogError(ERROR_LOG);
                value = 0;
            } else if(isStringAndEmpty(result)) {
                value = 0;
            } else {
                value = Convert.ToSingle(atof(result));
            }
            return true;
        } else {
            value = 0;
            return false;
        }
    }




    //add lxg C++重置
    // simon:mark
    // 2017-2-5 Fix runtime logic error.
    public static void assign<T>(this List<T> arr, int n, T v)  {
        if(arr == null) {
            arr = new List<T>();
        }
        arr.Clear();
        for(int i = 0; i < n; i++) {
            //arr[i] = v;
            arr.Add(v);
        }
    }

    public static void assign<T>(this Array source, int n, T v) {
        if(source == null) {
            source = new T[n];
            for(int i = 0; i < n; i++) {
                source.SetValue(v, i);
            }
        } else {
            n = source.Length <= n ? source.Length : n;
            for(int i = 0; i < n; i++) {
                source.SetValue(v, i);
            }
        }
    }

    //add lxg 2017.2.6 纯翻译
    public static int Count(this IList list) {
        if(list == null) {
            return 0;
        }
        return list.Count;
    }

    public static int Count(this Dictionary<string, object> dict) {
        if(dict == null) {
            return 0;
        }
        return dict.Count;
    }
    public static Vector2 Convert2(this Vector3 pos) {
        return new Vector2(pos.x, pos.y);
    }
}
}
